﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 群体行为控制器 - 管理整个群体的创建、更新和邻居检测
/// 实现Boid算法的核心逻辑，控制群体中每个个体的行为
/// </summary>
public class Flock : MonoBehaviour
{
    [Header("群体设置")]
    [Tooltip("群体个体的预制体")]
    public FlockAgent agentPrefab;
    
    [Tooltip("存储所有群体个体的列表")]
    List<FlockAgent> agents = new List<FlockAgent>();
    
    [Tooltip("群体行为策略，决定个体如何移动")]
    public FlockBehavior behavior;

    [Header("群体参数")]
    [Range(10, 500)]
    [Tooltip("群体初始个体数量")]
    public int startingCount = 250;
    
    [Tooltip("个体密度系数，用于计算初始生成范围")]
    const float AgentDensity = 0.08f;

    [Header("移动参数")]
    [Range(1f, 100f)]
    [Tooltip("驱动力系数，影响移动的强度")]
    public float driveFactor = 10f;
    
    [Range(1f, 100f)]
    [Tooltip("最大移动速度")]
    public float maxSpeed = 5f;
    
    [Range(1f, 10f)]
    [Tooltip("邻居检测半径")]
    public float neighborRadius = 1.5f;
    
    [Range(0f, 1f)]
    [Tooltip("避免碰撞半径倍数，相对于邻居半径")]
    public float avoidanceRadiusMultiplier = 0.5f;

    [Header("内部计算变量")]
    [Tooltip("最大速度的平方值，用于优化距离比较")]
    float squareMaxSpeed;
    
    [Tooltip("邻居半径的平方值，用于优化距离比较")]
    float squareNeighborRadius;
    
    [Tooltip("避免碰撞半径的平方值，用于优化距离比较")]
    float squareAvoidanceRadius;
    
    /// <summary>
    /// 获取避免碰撞半径的平方值（只读属性）
    /// </summary>
    public float SquareAvoidanceRadius { get { return squareAvoidanceRadius; } }

    /// <summary>
    /// 初始化群体系统
    /// 计算优化变量并创建指定数量的群体个体
    /// </summary>
    void Start()
    {
        // 预计算平方值以优化距离比较性能
        squareMaxSpeed = maxSpeed * maxSpeed;
        squareNeighborRadius = neighborRadius * neighborRadius;
        squareAvoidanceRadius = squareNeighborRadius * avoidanceRadiusMultiplier * avoidanceRadiusMultiplier;

        // 创建群体个体
        for (int i = 0; i < startingCount; i++)
        {
            // 在圆形区域内随机生成位置
            Vector2 randomPosition = Random.insideUnitCircle * startingCount * AgentDensity;
            // 随机生成朝向角度
            Quaternion randomRotation = Quaternion.Euler(Vector3.forward * Random.Range(0f, 360f));
            
            FlockAgent newAgent = Instantiate(agentPrefab, randomPosition, randomRotation, transform);
            newAgent.name = "Agent " + i;
            newAgent.Initialize(this);
            agents.Add(newAgent);
        }
    }

    /// <summary>
    /// 每帧更新所有群体个体的行为
    /// 计算每个个体的移动向量并应用到个体上
    /// </summary>
    void Update()
    {
        foreach (FlockAgent agent in agents)
        {
            // 获取当前个体周围的邻居对象
            List<Transform> context = GetNearbyObjects(agent);

            // 演示用代码：根据邻居数量改变颜色（已注释）
            //agent.GetComponentInChildren<SpriteRenderer>().color = Color.Lerp(Color.white, Color.red, context.Count / 6f);

            // 使用行为策略计算移动向量
            Vector2 move = behavior.CalculateMove(agent, context, this);
            move *= driveFactor;
            
            // 限制最大速度
            if (move.sqrMagnitude > squareMaxSpeed)
            {
                move = move.normalized * maxSpeed;
            }
            
            // 应用移动
            agent.Move(move);
        }
    }

    /// <summary>
    /// 获取指定个体周围的邻居对象
    /// 使用物理检测在邻居半径内查找所有碰撞体
    /// </summary>
    /// <param name="agent">要检测邻居的个体</param>
    /// <returns>邻居对象的Transform列表</returns>
    List<Transform> GetNearbyObjects(FlockAgent agent)
    {
        List<Transform> context = new List<Transform>();
        
        // 使用2D物理检测在指定半径内查找所有碰撞体
        Collider2D[] contextColliders = Physics2D.OverlapCircleAll(agent.transform.position, neighborRadius);
        
        // 过滤掉自身，只保留其他对象
        foreach (Collider2D c in contextColliders)
        {
            if (c != agent.AgentCollider)
            {
                context.Add(c.transform);
            }
        }
        
        return context;
    }

}
